#include "Session.h"
#include <cstring>
#include <functional>
#include <iostream>
#include "Server.h"
#include "const.h"
#include "boost/uuid/uuid.hpp"
#include "boost/uuid/uuid_generators.hpp"
#include "boost/uuid/uuid_io.hpp"

Session::Session(boost::asio::io_context& io_context,Server *server)
: socket_(io_context),server_(server),_b_head_parse(false),
_recv_head_node(std::make_shared<MsgNode>(HEAD_TOTAL_LEN)),_b_close(false)
{
    boost::uuids::uuid a_uuid = boost::uuids::random_generator()();
    uuid_ = boost::uuids::to_string(a_uuid);
}

Session::~Session()
{
    std::cout << "Session::~Session" << std::endl;
}

void Session::Start()
{
    #if 0
    memset(_data, 0, sizeof(_data));
    socket_.async_read_some(boost::asio::buffer(_data,sizeof(_data)),
        std::bind(&Session::HandleRead, this, std::placeholders::_1, std::placeholders::_2,shared_from_this()));
    #else
    //异步调用HandleReadHead函数
    boost::asio::async_read(socket_,boost::asio::buffer(_recv_head_node->_msg,HEAD_LENGTH),
            std::bind(&Session::HandleReadHead, this, std::placeholders::_1, std::placeholders::_2, shared_from_this()));
    #endif
}


void Session::HandleRead(const boost::system::error_code &ec,
        std::size_t bytes_transferred,std::shared_ptr<Session> session)
{
    if(ec)
    {
        std::cout << "HandleRead error error value: " << ec.value() << " message: " << ec.message() << std::endl;
        server_->ClearSession(uuid_);
        Close();
        return;
    }
    int copy_len=0;
    while(bytes_transferred>0)
    {
        if (!_b_head_parse) {
            //收到的数据不足头部大小
            if (bytes_transferred + _recv_head_node->_cur_len < HEAD_TOTAL_LEN) 
            {
                memcpy(_recv_head_node->_msg + _recv_head_node->_cur_len, _data+ copy_len, bytes_transferred);
                _recv_head_node->_cur_len += bytes_transferred;
                ::memset(_data, 0, MAX_LENGTH);
                socket_.async_read_some(boost::asio::buffer(_data, MAX_LENGTH), 
                    std::bind(&Session::HandleRead, this, std::placeholders::_1, std::placeholders::_2, shared_from_this()));
                return;
            }
            //收到的数据比头部多
            //头部剩余未复制的长度
            int head_remain = HEAD_TOTAL_LEN - _recv_head_node->_cur_len;
            memcpy(_recv_head_node->_msg + _recv_head_node->_cur_len, _data+copy_len, head_remain);
            //更新已处理的data长度和剩余未处理的长度
            copy_len += head_remain;
            bytes_transferred -= head_remain;

            //获取消息ID
            short msg_id=0;
            memcpy(&msg_id,_recv_head_node->_msg,HEAD_ID_LEN);
            //网络字节序转化为本地字节序
            msg_id=boost::asio::detail::socket_ops::network_to_host_short(msg_id);
            std::cout << "msg_id is " << msg_id << std::endl;

            //获取头部数据
            short data_len = 0;
            memcpy(&data_len, _recv_head_node->_msg+HEAD_ID_LEN, HEAD_DATA_LEN);
            //网络字节序转化为本地字节序
            data_len=boost::asio::detail::socket_ops::network_to_host_short(data_len);
            std::cout << "data_len is " << data_len << std::endl;
            //头部长度非法
            if (data_len > MAX_LENGTH) {
                std::cout << "invalid data length is " << data_len << std::endl;
                server_->ClearSession(uuid_);
                return;
            }
            _recv_msg_node = std::make_shared<RecvNode>(data_len,msg_id);

            //消息的长度小于头部规定的长度，说明数据未收全，则先将部分消息放到接收节点里
            if (bytes_transferred < data_len) {
                memcpy(_recv_msg_node->_msg + _recv_msg_node->_cur_len, _data + copy_len, bytes_transferred);
                _recv_msg_node->_cur_len += bytes_transferred;
                ::memset(_data, 0, MAX_LENGTH);
                socket_.async_read_some(boost::asio::buffer(_data, MAX_LENGTH), 
                    std::bind(&Session::HandleRead, this, std::placeholders::_1, std::placeholders::_2, shared_from_this()));
                //头部处理完成
                _b_head_parse = true;
                return;
            }

            memcpy(_recv_msg_node->_msg + _recv_msg_node->_cur_len, _data + copy_len, data_len);
            _recv_msg_node->_cur_len += data_len;
            copy_len += data_len;
            bytes_transferred -= data_len;
            _recv_msg_node->_msg[_recv_msg_node->_total_len] = '\0';
            std::cout << "receive data is " << _recv_msg_node->_msg << std::endl;

            /**
             * 此处可以增加逻辑操作
             */


            //此处可以调用Send发送测试
            Send(_recv_msg_node->_msg, _recv_msg_node->_total_len,_recv_msg_node->_msg_id);
            //继续轮询剩余未处理数据
            _b_head_parse = false;
            _recv_head_node->Clear();
            if (bytes_transferred <= 0) {
                ::memset(_data, 0, MAX_LENGTH);
                socket_.async_read_some(boost::asio::buffer(_data, MAX_LENGTH), 
                    std::bind(&Session::HandleRead, this, std::placeholders::_1, std::placeholders::_2, shared_from_this()));
                return;
            }
            continue;
        }

        //已经处理完头部，处理上次未接受完的消息数据
        //接收的数据仍不足剩余未处理的
        int remain_msg = _recv_msg_node->_total_len - _recv_msg_node->_cur_len;
        if (bytes_transferred < remain_msg) {
            memcpy(_recv_msg_node->_msg + _recv_msg_node->_cur_len, _data + copy_len, bytes_transferred);
            _recv_msg_node->_cur_len += bytes_transferred;
            ::memset(_data, 0, MAX_LENGTH);
            socket_.async_read_some(boost::asio::buffer(_data, MAX_LENGTH), 
                std::bind(&Session::HandleRead, this, std::placeholders::_1, std::placeholders::_2, shared_from_this()));
            return;
        }
        memcpy(_recv_msg_node->_msg + _recv_msg_node->_cur_len, _data + copy_len, remain_msg);
        _recv_msg_node->_cur_len += remain_msg;
        bytes_transferred -= remain_msg;
        copy_len += remain_msg;
        _recv_msg_node->_msg[_recv_msg_node->_total_len] = '\0';
        std::cout << "receive data is " << _recv_msg_node->_msg << std::endl;
        //此处可以调用Send发送测试
        Send(_recv_msg_node->_msg, _recv_msg_node->_total_len,_recv_msg_node->_msg_id);
        //继续轮询剩余未处理数据
        _b_head_parse = false;
        _recv_head_node->Clear();
        if (bytes_transferred <= 0) {
            ::memset(_data, 0, MAX_LENGTH);
            socket_.async_read_some(boost::asio::buffer(_data, MAX_LENGTH),
                std::bind(&Session::HandleRead, this, std::placeholders::_1, std::placeholders::_2, shared_from_this()));
            return;
        }
        continue;
	}
}

void Session::HandleWrite(const boost::system::error_code &ec,std::shared_ptr<Session> session)
{
    if(ec)
    {
        std::cout << "HandleWrite error error value: " << ec.value() << " message: " << ec.message() << std::endl;
        server_->ClearSession(uuid_);
        Close();
        return;
    }
    //发送下一条数据
    std::lock_guard<std::mutex> lock(_send_lock);
    _send_queue.pop();
    if(!_send_queue.empty())
    {
        auto msgNode = _send_queue.front();
        //服务器继续等待下一次读取
        boost::asio::async_write(socket_,boost::asio::buffer(msgNode->_msg+msgNode->_cur_len,
                                    msgNode->_total_len-msgNode->_cur_len),
                                    std::bind(&Session::HandleWrite, this, std::placeholders::_1,shared_from_this()));
    }
}

void Session::Send(const std::string msg,short msgid)
{
    Send(msg.c_str(),msg.size(),msgid);
}
void Session::Send(const char*msg,int max_length,short msgid)
{
    auto msgNode = std::make_shared<SendNode>(msg,max_length,msgid);
    std::lock_guard<std::mutex> lock(_send_lock);
    //获取队列的长度
    int que_size = _send_queue.size();
    //如果队列长度过长，就报错并退出
    if(que_size > MAX_SENDQUE)
    {
        std::cout << "Send error: queue size is " << que_size << " max queue size is " << MAX_SENDQUE << std::endl;
        return;
    }


    //    加入发送队列
    _send_queue.push(msgNode);
    //    如果是第一个数据，直接发送
    if(_send_queue.size() == 1)
    {
        msgNode = _send_queue.front();
        boost::asio::async_write(socket_,boost::asio::buffer(msgNode->_msg+msgNode->_cur_len,
                                    msgNode->_total_len-msgNode->_cur_len),
                                    std::bind(&Session::HandleWrite, this, std::placeholders::_1,shared_from_this()));
    }

}

void Session::Close()
{
    socket_.close();
    _b_close = true;
}

void Session::HandleReadHead(const boost::system::error_code &ec, std::size_t bytes_transferred,std::shared_ptr<Session> session)
{
    if(ec)
    {
        std::cout<<"HandleReadHead error error value: " << ec.value() << " message: " << ec.message() << std::endl;
        server_->ClearSession(uuid_);
        Close();
        return;
    }

    //判断接收的头部是否完成
    if(bytes_transferred <HEAD_LENGTH)
    {
        std::cout<<"Read head length error\n";
        server_->ClearSession(uuid_);
        Close();
        return;
    }
    //解析头部
    short msglen = 0;
    memcpy(&msglen,_recv_head_node->_msg,HEAD_LENGTH);
    msglen = boost::asio::detail::socket_ops::host_to_network_short(msglen);
    //构建消息节点
    _recv_msg_node = std::make_shared<MsgNode>(msglen);
    std::cout<<"Read msg length is "<<msglen<<std::endl;
    //判断消息长度是否超过最大长度
    if(msglen > MAX_LENGTH)
    {
        std::cout<<"Read msg length error\n";
        server_->ClearSession(uuid_);
        Close();
        return;
    }
    //异步调用HandleReadMsg读取消息体
    boost::asio::async_read(socket_,boost::asio::buffer(_recv_msg_node->_msg,_recv_msg_node->_total_len),
            std::bind(&Session::HandleReadMsg, this, std::placeholders::_1, std::placeholders::_2, shared_from_this()));

}
void Session::HandleReadMsg(const boost::system::error_code &ec, std::size_t bytes_transferred,std::shared_ptr<Session> session)
{
    if(ec)
    {
        std::cout<<"HandleReadMsg error error value: " << ec.value() << " message: " << ec.message() << std::endl;
        server_->ClearSession(uuid_);
        Close();
        return;
    }
    //判断接收的消息是否完成
    if(bytes_transferred < _recv_msg_node->_total_len)
    {
        std::cout<<"Read msg length error\n";
        server_->ClearSession(uuid_);
        Close();
        return;
    }
    _recv_msg_node->_msg[_recv_msg_node->_total_len] = '\0';
    std::cout << "receive data is " << _recv_msg_node->_msg << std::endl;
    //将消息加入处理队列
    Send(_recv_msg_node->_msg, _recv_msg_node->_total_len,_recv_msg_node->_msg_id);
    _recv_head_node->Clear();
    //继续异步回调头部读取函数
    boost::asio::async_read(socket_,boost::asio::buffer(_recv_head_node->_msg,HEAD_LENGTH),
            std::bind(&Session::HandleReadHead, this, std::placeholders::_1, std::placeholders::_2, shared_from_this()));
}